package com.wz.jaav.util;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class CommonUtils {

    /**
     * Mapped File way MappedByteBuffer 可以在处理大文件时，提升性能
     *
     * @param filename
     * @return
     * @throws IOException
     */
    public static byte[] toByteArray(String filename) throws IOException {

        FileChannel fc = null;
        try {
            fc = new RandomAccessFile(filename, "r").getChannel();
            MappedByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0,
                    fc.size()).load();
            byte[] result = new byte[(int) fc.size()];
            if (byteBuffer.remaining() > 0) {
                byteBuffer.get(result, 0, byteBuffer.remaining());
            }
            return result;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                fc.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getClassAbsPath(String cpOption, String className){
        return cpOption + "\\" + className.replace(".", "\\") + ".class";
    }

    final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
    public static String bytesToHex(byte[] bytes) {
        char[] hexChars = new char[bytes.length * 2];
        for ( int j = 0; j < bytes.length; j++ ) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }

    public static int bytes2Int(byte[] bytes ) {
        int int1 = (bytes[0]&0xff) << 24;
        int int2 = (bytes[1]&0xff) << 16;
        int int3 = (bytes[2]&0xff) << 8;
        int int4 = (bytes[3]&0xff);
        return int1|int2|int3|int4;
    }

    public static short byteToShort(byte[] b) {
        return (short) (((b[0] << 8) | b[1] & 0xff));
    }

    public final static String readUTF(int length, byte[] in) throws UTFDataFormatException {
        int utflen = length;
        byte[] bytearr = in;
        char[] chararr = new char[utflen];
        int c, char2, char3;
        int count = 0;
        int chararr_count=0;

        // 从“数据输入流”中读取数据并存储到字节数组bytearr中；从bytearr的位置0开始存储，存储长度为utflen。
        // 注意，这里是存储到字节数组！而且读取的是全部的数据。
//        in.readFully(bytearr, 0, utflen);

        // 将“字节数组bytearr”中的数据 拷贝到 “字符数组chararr”中
        // 注意：这里相当于“预处理的输入流中单字节的符号”，因为UTF-8是1-4个字节可变的。
        while (count < utflen) {
            // 将每个字节转换成int值
            c = (int) bytearr[count] & 0xff;
            // UTF-8的每个字节的值都不会超过127；所以，超过127，则退出。
            if (c > 127) break;
            count++;
            // 将c保存到“字符数组chararr”中
            chararr[chararr_count++]=(char)c;
        }

        // 处理完输入流中单字节的符号之后，接下来我们继续处理。
        while (count < utflen) {
            // 下面语句执行了2步操作。
            // (01) 将字节由 “byte类型” 转换成 “int类型”。
            //      例如， “11001010” 转换成int之后，是 “00000000 00000000 00000000 11001010”
            // (02) 将 “int类型” 的数据左移4位
            //      例如， “00000000 00000000 00000000 11001010” 左移4位之后，变成 “00000000 00000000 00000000 00001100”
            c = (int) bytearr[count] & 0xff;
            switch (c >> 4) {
                // 若 UTF-8 是单字节，即 bytearr[count] 对应是 “0xxxxxxx” 形式；
                // 则 bytearr[count] 对应的int类型的c的取值范围是 0-7。
                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
                    /* 0xxxxxxx*/
                    count++;
                    chararr[chararr_count++]=(char)c;
                    break;

                // 若 UTF-8 是双字节，即 bytearr[count] 对应是 “110xxxxx  10xxxxxx” 形式中的第一个，即“110xxxxx”
                // 则 bytearr[count] 对应的int类型的c的取值范围是 12-13。
                case 12: case 13:
                    /* 110x xxxx   10xx xxxx*/
                    count += 2;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                                "malformed input: partial character at end");
                    char2 = (int) bytearr[count-1];
                    if ((char2 & 0xC0) != 0x80)
                        throw new UTFDataFormatException(
                                "malformed input around byte " + count);
                    chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
                            (char2 & 0x3F));
                    break;

                // 若 UTF-8 是三字节，即 bytearr[count] 对应是 “1110xxxx  10xxxxxx  10xxxxxx” 形式中的第一个，即“1110xxxx”
                // 则 bytearr[count] 对应的int类型的c的取值是14 。
                case 14:
                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
                    count += 3;
                    if (count > utflen)
                        throw new UTFDataFormatException(
                                "malformed input: partial character at end");
                    char2 = (int) bytearr[count-2];
                    char3 = (int) bytearr[count-1];
                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
                        throw new UTFDataFormatException(
                                "malformed input around byte " + (count-1));
                    chararr[chararr_count++]=(char)(((c     & 0x0F) << 12) |
                            ((char2 & 0x3F) << 6)  |
                            ((char3 & 0x3F) << 0));
                    break;

                // 若 UTF-8 是四字节，即 bytearr[count] 对应是 “11110xxx 10xxxxxx  10xxxxxx  10xxxxxx” 形式中的第一个，即“11110xxx”
                // 则 bytearr[count] 对应的int类型的c的取值是15
                default:
                    /* 10xx xxxx,  1111 xxxx */
                    throw new UTFDataFormatException(
                            "malformed input around byte " + count);
            }
        }
        // The number of chars produced may be less than utflen
        return new String(chararr, 0, chararr_count);
    }

    public static void main(String[] args) {
//        System.out.println(getClassAbsPath("C:\\Users\\Administrator\\Desktop" , "com.wz.test2"));
    }
}